import re

from django import forms
from django_redis import get_redis_connection
from django.db.models import Q
from django.contrib.auth import login,logout

from verifications.constants import SMS_CODE_NUMS
from .models import Users
from user import constants

class RegisterForm(forms.Form):
    '''
    注册校验表单
    '''
    username = forms.CharField(label='用户名', max_length=20, min_length=5,
                               error_messages={"min_length": "用户名长度要大于5", "max_length": "用户名长度要小于20",
                                               "required": "用户名不能为空"}
                               )
    password = forms.CharField(label='密码', max_length=20, min_length=6,
                               error_messages={"min_length": "密码长度要大于6", "max_length": "密码长度要小于20",
                                               "required": "密码不能为空"}
                               )
    password_repeat = forms.CharField(label='确认密码', max_length=20, min_length=6,
                                      error_messages={"min_length": "密码长度要大于6", "max_length": "密码长度要小于20",
                                                      "required": "密码不能为空"}
                                      )
    mobile = forms.CharField(label='手机号', max_length=11, min_length=11,
                             error_messages={"min_length": "手机号长度有误", "max_length": "手机号长度有误",
                                             "required": "手机号不能为空"})
    sms_code = forms.CharField(label='短信验证码', max_length=SMS_CODE_NUMS, min_length=SMS_CODE_NUMS,
                               error_messages={"min_length": "短信验证码长度有误", "max_length": "短信验证码长度有误",
                                               "required": "短信验证码不能为空"})

    def clean_mobile(self):
        """
        mobile 单字段清洗
        """
        tel = self.cleaned_data.get('mobile')#获取mobile字段
        if not re.match(r"^1[3-9]\d{9}$", tel):#如果没有正确匹配手机号
            raise forms.ValidationError("手机号码格式不正确")

        if Users.objects.filter(mobile=tel).exists():#如果手机号存在
            raise forms.ValidationError("手机号已注册，请重新输入！")
        return tel

    def clean_username(self):
        '''
        判断用户名是否存在
        '''
        uname = self.cleaned_data.get('username')
        if Users.objects.filter(username=uname).exists():
            raise forms.ValidationError('用户名已注册')
        return uname

    def clean(self):
        """
        联合字段清洗
        """
        cleaned_data = super().clean()#继承clean方法,数据存放在cleaned_data
        passwd = cleaned_data.get('password')
        passwd_repeat = cleaned_data.get('password_repeat')

        if passwd != passwd_repeat:#如果连个密码不一样
            raise forms.ValidationError("两次密码不一致")

        #获取手机号 短信验证码
        tel = cleaned_data.get('mobile')
        sms_text = cleaned_data.get('sms_code')

        # 建立redis连接
        redis_conn = get_redis_connection(alias='verify_codes')
        sms_fmt = "sms_{}".format(tel).encode('utf-8')#生成key
        #通过key查值
        real_sms = redis_conn.get(sms_fmt)
        con_redis = get_redis_connection(alias='verify_codes')
        con_redis.delete(sms_fmt)
        #如果key不存在 或者 两个key不相等
        if (not real_sms) or (sms_text != real_sms.decode('utf-8')):
            raise forms.ValidationError("短信验证码错误")

class LoginForm(forms.Form):
    '''
    登录表单校验 用户名/手机号 密码 记住我
    '''
    user_account = forms.CharField()
    password = forms.CharField(label='密码', max_length=20, min_length=6,
                               error_messages={"min_length": "密码长度要大于6", "max_length": "密码长度要小于20",
                                               "required": "密码不能为空"}
                               )
    remember_me = forms.BooleanField(required=False)#默认设置为False
    def __init__(self,*args,**kwargs):#重新构造方法为了传递request
        self.request = kwargs.pop('request',None)
        super().__init__(*args,**kwargs)
    def clean_user_account(self):
        '''
        清洗用户账号
        '''
        user_info = self.cleaned_data.get('user_account')

        if not user_info:
            raise forms.ValidationError("用户账号不可为空")
        if not re.match(r"^1[3-9]\d{9}$",user_info) and (len(user_info)<5 or len(user_info)>20):
            #如果匹配出不符合手机号格式 且 长度小于5或大于20(既不是手机号,又不是用户名)
            raise forms.ValidationError("用户账号格式不正确,请重新输入")
        return user_info
    def clean(self):
        '''
        联合校验-->数据库
        '''
        # 1.获取清洗之后的参数
        cleaned_data =super().clean()
        user_info = cleaned_data.get('user_account')
        passwd = cleaned_data.get('password')
        hold_login = cleaned_data.get('remember_me')

        # 2.查询数据库,校验用户吗
        user_queryset = Users.objects.filter(Q(username=user_info) | Q(mobile=user_info))#如果前面查不到去后面查
        if user_queryset:#如果用户存在
            user = user_queryset.first()
            # if user.password != passwd :
            # 数据库中的密码是加密过的,使用django自带的密码校验
            if user.check_password(passwd):
                if hold_login:#如果勾选记住我 设置会话信息
                    self.request.session.set_expiry(
                        constants.USER_SESSION_EXPIRES)# None默认2周 0为关闭即删除
                else:
                    self.request.session.set_expiry(0)  # None默认2周 0为关闭即删除
                login(self.request,user)
            else:
                raise forms.ValidationError("用户密码不正确")
        else:#用户不存在
            raise forms.ValidationError('用户账号不存在')
        # 3.是否设置用户会话记录
